package xyhoo.springframework.core.io;

import xyhoo.springframework.util.Assert;
import xyhoo.springframework.util.ClassUtils;
import xyhoo.springframework.util.StringUtils;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class ClassPathResource extends AbstractFileResolvingResource {

    private final String path;

    private final String absolutePath;

    private final ClassLoader classLoader;

    private final Class<?> clazz;

    public ClassPathResource(String path, Class<?> clazz) {
        this.path = StringUtils.cleanPath(path);
        String absolutePath = this.path;
        if (clazz != null && !absolutePath.startsWith("/")) {
            absolutePath = ClassUtils.classPackageAsResourcePath(clazz) + "/" + absolutePath;
        } else if (absolutePath.startsWith("/")) {
            absolutePath = absolutePath.substring(1);
        }
        this.absolutePath = absolutePath;

        this.classLoader = null;
        this.clazz = clazz;
    }

    public ClassPathResource(String path, ClassLoader classLoader) {
        Assert.notNull(path, "Path must not be null");
        String pathToUse = StringUtils.cleanPath(path);
        if (pathToUse.startsWith("/")) {
            pathToUse = pathToUse.substring(1);
        }
        this.path = pathToUse;
        this.absolutePath = pathToUse;
        this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
        clazz = null;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        InputStream is;
        if (this.clazz != null) {
            is = this.clazz.getResourceAsStream(this.path);
        } else if (this.classLoader != null) {
            is = this.classLoader.getResourceAsStream(this.absolutePath);
        } else {
            is = ClassLoader.getSystemResourceAsStream(this.absolutePath);
        }
        if (is == null) {
            throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
        }
        return is;
    }

    @Override
    public String getDescription() {
        return "class path resource [" + this.absolutePath + "]";
    }
}
